home *** CD-ROM | disk | FTP | other *** search
/ OpenGL Superbible (2nd Edition) / OpenGL SuperBible e2.iso / tools / Mesa-3.0 / SRC / FEEDBACK.C < prev    next >
Encoding:
C/C++ Source or Header  |  1998-02-21  |  9.8 KB  |  410 lines

  1. /* $Id: feedback.c,v 3.3 1998/02/21 01:32:49 brianp Exp $ */
  2.  
  3. /*
  4.  * Mesa 3-D graphics library
  5.  * Version:  3.0
  6.  * Copyright (C) 1995-1998  Brian Paul
  7.  *
  8.  * This library is free software; you can redistribute it and/or
  9.  * modify it under the terms of the GNU Library General Public
  10.  * License as published by the Free Software Foundation; either
  11.  * version 2 of the License, or (at your option) any later version.
  12.  *
  13.  * This library is distributed in the hope that it will be useful,
  14.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  16.  * Library General Public License for more details.
  17.  *
  18.  * You should have received a copy of the GNU Library General Public
  19.  * License along with this library; if not, write to the Free
  20.  * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  21.  */
  22.  
  23.  
  24. /*
  25.  * $Log: feedback.c,v $
  26.  * Revision 3.3  1998/02/21 01:32:49  brianp
  27.  * fixed bug in gl_InitNames()
  28.  *
  29.  * Revision 3.2  1998/02/08 20:18:20  brianp
  30.  * removed unneeded headers
  31.  *
  32.  * Revision 3.1  1998/02/04 00:34:29  brianp
  33.  * fixed a few cast problems for Amiga StormC compiler
  34.  *
  35.  * Revision 3.0  1998/01/31 20:52:30  brianp
  36.  * initial rev
  37.  *
  38.  */
  39.  
  40.  
  41. #ifdef PC_HEADER
  42. #include "all.h"
  43. #else
  44. #include <assert.h>
  45. #include <stdio.h>
  46. #include "context.h"
  47. #include "feedback.h"
  48. #include "macros.h"
  49. #include "types.h"
  50. #endif
  51.  
  52.  
  53.  
  54. #define FB_3D        0x01
  55. #define FB_4D        0x02
  56. #define FB_INDEX    0x04
  57. #define FB_COLOR    0x08
  58. #define FB_TEXTURE    0X10
  59.  
  60.  
  61.  
  62. void
  63. gl_FeedbackBuffer( GLcontext *ctx, GLsizei size, GLenum type, GLfloat *buffer )
  64. {
  65.    if (ctx->RenderMode==GL_FEEDBACK || INSIDE_BEGIN_END(ctx)) {
  66.       gl_error( ctx, GL_INVALID_OPERATION, "glFeedbackBuffer" );
  67.       return;
  68.    }
  69.  
  70.    if (size<0) {
  71.       gl_error( ctx, GL_INVALID_VALUE, "glFeedbackBuffer(size<0)" );
  72.       return;
  73.    }
  74.    if (!buffer) {
  75.       gl_error( ctx, GL_INVALID_VALUE, "glFeedbackBuffer(buffer==NULL)" );
  76.       ctx->Feedback.BufferSize = 0;
  77.       return;
  78.    }
  79.  
  80.    switch (type) {
  81.       case GL_2D:
  82.      ctx->Feedback.Mask = 0;
  83.          ctx->Feedback.Type = type;
  84.      break;
  85.       case GL_3D:
  86.      ctx->Feedback.Mask = FB_3D;
  87.          ctx->Feedback.Type = type;
  88.      break;
  89.       case GL_3D_COLOR:
  90.      ctx->Feedback.Mask = FB_3D
  91.                            | (ctx->Visual->RGBAflag ? FB_COLOR : FB_INDEX);
  92.          ctx->Feedback.Type = type;
  93.      break;
  94.       case GL_3D_COLOR_TEXTURE:
  95.      ctx->Feedback.Mask = FB_3D
  96.                            | (ctx->Visual->RGBAflag ? FB_COLOR : FB_INDEX)
  97.                        | FB_TEXTURE;
  98.          ctx->Feedback.Type = type;
  99.      break;
  100.       case GL_4D_COLOR_TEXTURE:
  101.      ctx->Feedback.Mask = FB_3D | FB_4D
  102.                            | (ctx->Visual->RGBAflag ? FB_COLOR : FB_INDEX)
  103.                        | FB_TEXTURE;
  104.          ctx->Feedback.Type = type;
  105.      break;
  106.       default:
  107.      ctx->Feedback.Mask = 0;
  108.          gl_error( ctx, GL_INVALID_ENUM, "glFeedbackBuffer" );
  109.    }
  110.  
  111.    ctx->Feedback.BufferSize = size;
  112.    ctx->Feedback.Buffer = buffer;
  113.    ctx->Feedback.Count = 0;
  114. }
  115.  
  116.  
  117.  
  118. void gl_PassThrough( GLcontext *ctx, GLfloat token )
  119. {
  120.    if (INSIDE_BEGIN_END(ctx)) {
  121.       gl_error( ctx, GL_INVALID_OPERATION, "glPassThrough" );
  122.       return;
  123.    }
  124.  
  125.    if (ctx->RenderMode==GL_FEEDBACK) {
  126.       FEEDBACK_TOKEN( ctx, (GLfloat) (GLint) GL_PASS_THROUGH_TOKEN );
  127.       FEEDBACK_TOKEN( ctx, token );
  128.    }
  129. }
  130.  
  131.  
  132.  
  133. /*
  134.  * Put a vertex into the feedback buffer.
  135.  */
  136. void gl_feedback_vertex( GLcontext *ctx,
  137.                          GLfloat x, GLfloat y, GLfloat z, GLfloat w,
  138.              const GLfloat color[4], GLfloat index,
  139.              const GLfloat texcoord[4] )
  140. {
  141.    FEEDBACK_TOKEN( ctx, x );
  142.    FEEDBACK_TOKEN( ctx, y );
  143.    if (ctx->Feedback.Mask & FB_3D) {
  144.       FEEDBACK_TOKEN( ctx, z );
  145.    }
  146.    if (ctx->Feedback.Mask & FB_4D) {
  147.       FEEDBACK_TOKEN( ctx, w );
  148.    }
  149.    if (ctx->Feedback.Mask & FB_INDEX) {
  150.       FEEDBACK_TOKEN( ctx, index );
  151.    }
  152.    if (ctx->Feedback.Mask & FB_COLOR) {
  153.       FEEDBACK_TOKEN( ctx, color[0] );
  154.       FEEDBACK_TOKEN( ctx, color[1] );
  155.       FEEDBACK_TOKEN( ctx, color[2] );
  156.       FEEDBACK_TOKEN( ctx, color[3] );
  157.    }
  158.    if (ctx->Feedback.Mask & FB_TEXTURE) {
  159.       FEEDBACK_TOKEN( ctx, texcoord[0] );
  160.       FEEDBACK_TOKEN( ctx, texcoord[1] );
  161.       FEEDBACK_TOKEN( ctx, texcoord[2] );
  162.       FEEDBACK_TOKEN( ctx, texcoord[3] );
  163.    }
  164. }
  165.  
  166.  
  167.  
  168. /**********************************************************************/
  169. /*                              Selection                             */
  170. /**********************************************************************/
  171.  
  172.  
  173. /*
  174.  * NOTE: this function can't be put in a display list.
  175.  */
  176. void gl_SelectBuffer( GLcontext *ctx, GLsizei size, GLuint *buffer )
  177. {
  178.    if (INSIDE_BEGIN_END(ctx)) {
  179.       gl_error( ctx, GL_INVALID_OPERATION, "glSelectBuffer" );
  180.    }
  181.    if (ctx->RenderMode==GL_SELECT) {
  182.       gl_error( ctx, GL_INVALID_OPERATION, "glSelectBuffer" );
  183.    }
  184.    ctx->Select.Buffer = buffer;
  185.    ctx->Select.BufferSize = size;
  186.    ctx->Select.BufferCount = 0;
  187.  
  188.    ctx->Select.HitFlag = GL_FALSE;
  189.    ctx->Select.HitMinZ = 1.0;
  190.    ctx->Select.HitMaxZ = 0.0;
  191. }
  192.  
  193.  
  194. #define WRITE_RECORD( CTX, V )                    \
  195.     if (CTX->Select.BufferCount < CTX->Select.BufferSize) {    \
  196.        CTX->Select.Buffer[CTX->Select.BufferCount] = (V);    \
  197.     }                            \
  198.     CTX->Select.BufferCount++;
  199.  
  200.  
  201.  
  202. void gl_update_hitflag( GLcontext *ctx, GLfloat z )
  203. {
  204.    ctx->Select.HitFlag = GL_TRUE;
  205.    if (z < ctx->Select.HitMinZ) {
  206.       ctx->Select.HitMinZ = z;
  207.    }
  208.    if (z > ctx->Select.HitMaxZ) {
  209.       ctx->Select.HitMaxZ = z;
  210.    }
  211. }
  212.  
  213.  
  214.  
  215. static void write_hit_record( GLcontext *ctx )
  216. {
  217.    GLuint i;
  218.    GLuint zmin, zmax, zscale = (~0u);
  219.  
  220.    /* HitMinZ and HitMaxZ are in [0,1].  Multiply these values by */
  221.    /* 2^32-1 and round to nearest unsigned integer. */
  222.  
  223.    assert( ctx != NULL ); /* this line magically fixes a SunOS 5.x/gcc bug */
  224.    zmin = (GLuint) ((GLfloat) zscale * ctx->Select.HitMinZ);
  225.    zmax = (GLuint) ((GLfloat) zscale * ctx->Select.HitMaxZ);
  226.  
  227.    WRITE_RECORD( ctx, ctx->Select.NameStackDepth );
  228.    WRITE_RECORD( ctx, zmin );
  229.    WRITE_RECORD( ctx, zmax );
  230.    for (i=0;i<ctx->Select.NameStackDepth;i++) {
  231.       WRITE_RECORD( ctx, ctx->Select.NameStack[i] );
  232.    }
  233.  
  234.    ctx->Select.Hits++;
  235.    ctx->Select.HitFlag = GL_FALSE;
  236.    ctx->Select.HitMinZ = 1.0;
  237.    ctx->Select.HitMaxZ = -1.0;
  238. }
  239.  
  240.  
  241.  
  242. void gl_InitNames( GLcontext *ctx )
  243. {
  244.    if (INSIDE_BEGIN_END(ctx)) {
  245.       gl_error( ctx, GL_INVALID_OPERATION, "glInitNames" );
  246.    }
  247.    /* Record the hit before the HitFlag is wiped out again. */
  248.    if (ctx->RenderMode==GL_SELECT) {
  249.       if (ctx->Select.HitFlag) {
  250.          write_hit_record( ctx );
  251.       }
  252.    }
  253.    ctx->Select.NameStackDepth = 0;
  254.    ctx->Select.HitFlag = GL_FALSE;
  255.    ctx->Select.HitMinZ = 1.0;
  256.    ctx->Select.HitMaxZ = 0.0;
  257. }
  258.  
  259.  
  260.  
  261. void gl_LoadName( GLcontext *ctx, GLuint name )
  262. {
  263.    if (INSIDE_BEGIN_END(ctx)) {
  264.       gl_error( ctx, GL_INVALID_OPERATION, "glLoadName" );
  265.       return;
  266.    }
  267.    if (ctx->RenderMode!=GL_SELECT) {
  268.       return;
  269.    }
  270.    if (ctx->Select.NameStackDepth==0) {
  271.       gl_error( ctx, GL_INVALID_OPERATION, "glLoadName" );
  272.       return;
  273.    }
  274.    if (ctx->Select.HitFlag) {
  275.       write_hit_record( ctx );
  276.    }
  277.    if (ctx->Select.NameStackDepth<MAX_NAME_STACK_DEPTH) {
  278.       ctx->Select.NameStack[ctx->Select.NameStackDepth-1] = name;
  279.    }
  280.    else {
  281.       ctx->Select.NameStack[MAX_NAME_STACK_DEPTH-1] = name;
  282.    }
  283. }
  284.  
  285.  
  286. void gl_PushName( GLcontext *ctx, GLuint name )
  287. {
  288.    if (INSIDE_BEGIN_END(ctx)) {
  289.       gl_error( ctx, GL_INVALID_OPERATION, "glPushName" );
  290.       return;
  291.    }
  292.    if (ctx->RenderMode!=GL_SELECT) {
  293.       return;
  294.    }
  295.    if (ctx->Select.HitFlag) {
  296.       write_hit_record( ctx );
  297.    }
  298.    if (ctx->Select.NameStackDepth<MAX_NAME_STACK_DEPTH) {
  299.       ctx->Select.NameStack[ctx->Select.NameStackDepth++] = name;
  300.    }
  301.    else {
  302.       gl_error( ctx, GL_STACK_OVERFLOW, "glPushName" );
  303.    }
  304. }
  305.  
  306.  
  307.  
  308. void gl_PopName( GLcontext *ctx )
  309. {
  310.    if (INSIDE_BEGIN_END(ctx)) {
  311.       gl_error( ctx, GL_INVALID_OPERATION, "glPopName" );
  312.       return;
  313.    }
  314.    if (ctx->RenderMode!=GL_SELECT) {
  315.       return;
  316.    }
  317.    if (ctx->Select.HitFlag) {
  318.       write_hit_record( ctx );
  319.    }
  320.    if (ctx->Select.NameStackDepth>0) {
  321.       ctx->Select.NameStackDepth--;
  322.    }
  323.    else {
  324.       gl_error( ctx, GL_STACK_UNDERFLOW, "glPopName" );
  325.    }
  326. }
  327.  
  328.  
  329.  
  330. /**********************************************************************/
  331. /*                           Render Mode                              */
  332. /**********************************************************************/
  333.  
  334.  
  335.  
  336. /*
  337.  * NOTE: this function can't be put in a display list.
  338.  */
  339. GLint gl_RenderMode( GLcontext *ctx, GLenum mode )
  340. {
  341.    GLint result;
  342.  
  343.    if (INSIDE_BEGIN_END(ctx)) {
  344.       gl_error( ctx, GL_INVALID_OPERATION, "glRenderMode" );
  345.    }
  346.  
  347.    switch (ctx->RenderMode) {
  348.       case GL_RENDER:
  349.      result = 0;
  350.      break;
  351.       case GL_SELECT:
  352.      if (ctx->Select.HitFlag) {
  353.         write_hit_record( ctx );
  354.      }
  355.      if (ctx->Select.BufferCount > ctx->Select.BufferSize) {
  356.         /* overflow */
  357. #ifdef DEBUG
  358.             gl_warning(ctx, "Feedback buffer overflow");
  359. #endif
  360.         result = -1;
  361.      }
  362.      else {
  363.         result = ctx->Select.Hits;
  364.      }
  365.      ctx->Select.BufferCount = 0;
  366.      ctx->Select.Hits = 0;
  367.      ctx->Select.NameStackDepth = 0;
  368.      break;
  369.       case GL_FEEDBACK:
  370.      if (ctx->Feedback.Count > ctx->Feedback.BufferSize) {
  371.         /* overflow */
  372.         result = -1;
  373.      }
  374.      else {
  375.         result = ctx->Feedback.Count;
  376.      }
  377.      ctx->Feedback.Count = 0;
  378.      break;
  379.       default:
  380.      gl_error( ctx, GL_INVALID_ENUM, "glRenderMode" );
  381.      return 0;
  382.    }
  383.  
  384.    switch (mode) {
  385.       case GL_RENDER:
  386.          break;
  387.       case GL_SELECT:
  388.      if (ctx->Select.BufferSize==0) {
  389.         /* haven't called glSelectBuffer yet */
  390.         gl_error( ctx, GL_INVALID_OPERATION, "glRenderMode" );
  391.      }
  392.      break;
  393.       case GL_FEEDBACK:
  394.      if (ctx->Feedback.BufferSize==0) {
  395.         /* haven't called glFeedbackBuffer yet */
  396.         gl_error( ctx, GL_INVALID_OPERATION, "glRenderMode" );
  397.      }
  398.      break;
  399.       default:
  400.      gl_error( ctx, GL_INVALID_ENUM, "glRenderMode" );
  401.      return 0;
  402.    }
  403.  
  404.    ctx->RenderMode = mode;
  405.    ctx->NewState |= NEW_ALL;
  406.  
  407.    return result;
  408. }
  409.  
  410.